package com.example.mydownloader.netty

import android.text.TextUtils
import android.util.Base64
import com.example.mydownloader.config.globalConfig.UrlConfig
import com.example.mydownloader.config.thread.MyThreadPool
import com.example.mydownloader.data.model.inputdata.NettyConfig
import com.example.mydownloader.myconst.TransmissionData
import com.example.mydownloader.mymodule.encrypt.AESKey
import com.example.mydownloader.mymodule.gson.GsonUtil
import com.example.mydownloader.mymodule.http.HttpUtil
import com.example.mydownloader.mymodule.log.LogUtil
import com.example.mydownloader.mymodule.sharedpreferences.SPUtil
import com.google.gson.JsonObject
import java.lang.NullPointerException


/**
 * @Author: Wallace
 * @Description: 文件描述
 * @Date: 2022/1/31 18:47
 * @Modified: By yyyy-MM-dd
 */
object NettyManager {

    private var count: Int = 0
    var token: String = ""
    var nettyUrls: ArrayList<String> = arrayListOf()

    private var listener = object : NettyListener {

        override fun onReady(isChange: Boolean) {
            if (TextUtils.isEmpty(token)) {
                throw NullPointerException("token must be empty")
            }
            if (nettyUrls.size == 0) {
                throw NullPointerException("token must be empty")
            }
            if (isChange) {
                count = 0
            }
            if (count > nettyUrls.size) {
                throw IndexOutOfBoundsException("已无netty url可用")
            }
            val url = nettyUrls[count]
            val nettyConfig = getNettyConfig(token, url)
            if (nettyConfig == null) {
                onGetNettyConfigFail(count, url)
            } else {
                onGetNettyConfigSuccess(url = url, nettyConfig = nettyConfig)
            }
        }

        override fun onGetNettyConfigSuccess(url: String, nettyConfig: NettyConfig) {
            LogUtil.d("success $url")
            LogUtil.d("start to connect netty server with $nettyConfig")
            initAesKey()
            NettyClient.connect(nettyConfig.host, nettyConfig.port, this, 1)
        }

        override fun onGetNettyConfigFail(count1: Int, url1: String) {
            LogUtil.d("fail $url1 $count1")
            if (count1 == nettyUrls.size - 1) {
                LogUtil.d("fail $nettyUrls")
            } else {
                count = count1 + 1
                val url = nettyUrls[count]
                val nettyConfig = getNettyConfig(token, url)
                if (nettyConfig == null) {
                    onGetNettyConfigFail(count, url)
                } else {
                    onGetNettyConfigSuccess(url = url, nettyConfig = nettyConfig)
                }
            }
        }

        override fun onConnectSuccess(host: String, port: Int, connCount: Int) {
            LogUtil.d("connect netty server success: $host $port $connCount")
        }

        override fun onConnectFail(host: String, port: Int, connCount: Int, cause: Throwable) {
            LogUtil.d("connect netty server fail: $host $port $connCount times.try again")
            if (connCount >= 3) {
                LogUtil.d("connect netty server fail: $host $port $connCount times.no try again")
                LogUtil.e("$cause")
            } else {
                NettyClient.connect(host, port, this, connCount + 1)
            }
        }


        override fun onDisconnect() {
            TODO("Not yet implemented")
        }

    }

    fun setSome(token: String, nettyUrls: ArrayList<String>): NettyManager {
        this.token = token
        this.nettyUrls = nettyUrls
        return this
    }

    fun start(isChanged: Boolean = false) {
        MyThreadPool.threadPool.execute {
            LogUtil.d("正在启动Netty Client...")
            listener.onReady(isChanged)
        }
    }

    private fun getNettyConfig(token: String, nettyUrl: String): NettyConfig? {
        var nettyConfig: NettyConfig? = null
        val nettyConfigString = HttpUtil.get(
            url = UrlConfig.baseUrl + nettyUrl,
            headers = hashMapOf(
                TransmissionData.TOKEN to token
            ),
            data = null
        )
        val jsonObject = GsonUtil.toAny(nettyConfigString, JsonObject::class.java)
        if (jsonObject != null) {
            nettyConfig =
                NettyConfig(jsonObject.get("host").asString, jsonObject.get("port").asInt)
            LogUtil.d("nettyConfig = $nettyConfig")
        }
        return nettyConfig
    }

    var aesKey: AESKey? = null

    fun initAesKey() {
        // 获取AES的Key和iv
        val key = SPUtil.getString(TransmissionData.AES_KEY)
        val iv = SPUtil.getString(TransmissionData.AES_IV)
        if (TextUtils.isEmpty(key)) {
            throw NullPointerException("key = $key")
        }
        if (TextUtils.isEmpty(iv)) {
            throw NullPointerException("iv = $iv")
        }
        val keyByteArray = Base64.decode(key.toByteArray(), Base64.NO_WRAP)
        val ivByteArray = Base64.decode(iv.toByteArray(), Base64.NO_WRAP)
        aesKey = AESKey(keyByteArray, ivByteArray)
    }
}